/**
 * @Description:
 * @Author: Administrator
 * @Date: 2020-10-10 11:01
 */
package org.jsola.hr.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.jsola.admin.entity.DictItemDO;
import org.jsola.admin.entity.SiteDO;
import org.jsola.admin.vo.AreaReduceVO;
import org.jsola.admin.vo.AreaVO;
import org.jsola.common.*;
import org.jsola.core.Page;
import org.jsola.core.entity.BaseDO;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.*;
import org.jsola.hr.constant.FileType;
import org.jsola.hr.dao.IChildCompanyDAO;
import org.jsola.hr.dao.IStatisticsPageDao;
import org.jsola.hr.dto.CompanyAdditionalFieldsAddDTO;
import org.jsola.hr.entity.*;
import org.jsola.hr.provider.*;
import org.jsola.hr.query.*;
import org.jsola.hr.query.permission.RoleMemberQuery;
import org.jsola.hr.service.*;
import org.jsola.hr.vo.*;
import org.jsola.hr.vo.excel.ChildCompanyExportVO;
import org.jsola.hr.vo.excel.GroupCompanyExportVO;
import org.jsola.hr.vo.permission.RoleMemberVO;
import org.jsola.log.query.ServiceLogQuery;
import org.jsola.log.vo.ServiceLogListVO;
import org.jsola.user.core.TokenUser;
import org.jsola.user.query.UserQuery;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import tk.mybatis.mapper.entity.Example;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

import static org.jsola.hr.constant.HrConstants.*;
import static org.jsola.hr.constant.StatisticsPageColumn.EXPORT_COLUMN_NAME_MAP;

@Slf4j
@Service("statisticsPageServiceImpl")
public class StatisticsPageServiceImpl implements IStatisticsPageService {
    @Autowired
    private IStatisticsPageDao statisticsPageDao;

    @Autowired
    private IChildCompanyDAO childCompanyDAO;

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private IChildCompanyService childCompanyService;

    @Autowired
    private IUserProviderService userProviderService;

    @Autowired
    private IGroupCityService groupCityService;

    @Autowired
    private IGroupCompanyService groupCompanyService;

    @Autowired
    private ICompanyService companyService;

    @Autowired
    private IPermissionProviderService permissionProviderService;

    @Autowired
    private IContractProviderService contractProviderService;

    @Autowired
    private IEmpContactsService empContactsService;

    @Autowired
    private IEmpSocInfoService empSocInfoService;

    @Autowired
    private IMessageProviderService messageProviderService;

    @Autowired
    private IServiceLogProviderService serviceLogProviderService;

    @Autowired
    private IAdminProviderService adminProviderService;

    @Autowired
    private IEmpEducationService empEducationService;

    @Autowired
    private IChannelService channelService;

    @Autowired
    private IOperationEmpRecordService operationEmpRecordService;

    @Autowired
    private ICompanyAdditionalFieldsService companyAdditionalFieldsService;

    @Autowired
    private IEmpContractService empContractService;

    @Autowired
    private IEmpPaperContractService empPaperContractService;

    @Lazy
    @Autowired
    private IEmpAdditionalFieldsService empAdditionalFieldsService;

    /**
     * 工作性质code
     */
    private final String POST_TYPE = "POST_TYPE";

    @Override
    public InputStream todayAddExport(StatisicsPageEmpExportQuery statisicsPageEmpExportQuery, TokenUser tokenUser) {
        if (statisicsPageEmpExportQuery.getIsAll() != null && statisicsPageEmpExportQuery.getIsAll() == 1) {
            statisicsPageEmpExportQuery.getOperationEmpRecordQuery().setPageSize(99999);
            Page<EmpInfoVO> empInfoVOPage = operationEmpRecordService.queryEmpPageList(statisicsPageEmpExportQuery.getOperationEmpRecordQuery(), tokenUser);
            statisicsPageEmpExportQuery.setEmpInfoVOList(empInfoVOPage.getEntities());
        }

        List<DictItemDO> postTypeList = adminProviderService.selectAllDictItem(null, POST_TYPE, tokenUser);
        Map<String, String> postTypeMap = postTypeList.stream().collect(Collectors.toMap(DictItemDO::getDictItemValue, DictItemDO::getDictItemKey, (key1, key2) -> key2));

        //制作表头
        List<List<String>> list = new ArrayList<>();
        for (int i = 0; i < 8; i++) {
            ArrayList<String> list1 = new ArrayList<>();
            if (i == 0) {
                list1.add("姓名");
            } else if (i == 1) {
                list1.add("手机号");
            } else if (i == 2) {
                list1.add("身份证号");
            } else if (i == 3) {
                if (statisicsPageEmpExportQuery.getExportType() == 1) {
                    list1.add("用工单位");
                } else {
                    continue;
                }
            } else if (i == 4) {
                list1.add("工作性质");
            } else if (i == 5) {
                list1.add("渠道来源");
            } else if (i == 6) {
                list1.add("录入人");
            } else {
                list1.add("录入方式");
            }
            list.add(list1);

        }


        List<EmpInfoVO> EmpInfoVOS = statisicsPageEmpExportQuery.getEmpInfoVOList();
        //数据
        List<List<String>> dataList = new ArrayList<>();
        for (int i = 0; i < EmpInfoVOS.size(); i++) {
            List<String> dataInfoList = new ArrayList<>();
            dataInfoList.add(EmpInfoVOS.get(i).getName());
            dataInfoList.add(EmpInfoVOS.get(i).getPhone());
            dataInfoList.add(EmpInfoVOS.get(i).getIdCard());
            if (statisicsPageEmpExportQuery.getExportType() == 1) {
                dataInfoList.add(EmpInfoVOS.get(i).getCompanyName());
            }
            Integer postType = EmpInfoVOS.get(i).getPostType();
            if (postType != null) {
                dataInfoList.add(postTypeMap.get(String.valueOf(postType)));
//                if (postType == 1) {
//                    dataInfoList.add("劳务派遣");
//                } else if (postType == 2) {
//                    dataInfoList.add("外包");
//                } else if (postType == 3) {
//                    dataInfoList.add("社保代缴");
//                } else if (postType == 4) {
//                    dataInfoList.add("薪资代发");
//                } else if (postType == 5) {
//                    dataInfoList.add("其他");
//                }
            } else {
                dataInfoList.add(" ");
            }
            dataInfoList.add(EmpInfoVOS.get(i).getChannelName());
            dataInfoList.add(EmpInfoVOS.get(i).getInputName());
            Integer sourceType1 = EmpInfoVOS.get(i).getSourceType();
            if (sourceType1 != null) {
                if (sourceType1 == 1) {
                    dataInfoList.add("网页端");
                } else if (sourceType1 == 2) {
                    dataInfoList.add("手机端");
                } else if (sourceType1 == 3) {
                    dataInfoList.add("用工单位");
                }
            } else {
                dataInfoList.add(" ");
            }
            dataList.add(dataInfoList);
        }
        HorizontalCellStyleStrategy horizontalCellStyleStrategy = ExcelKit.generalTactics(false);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        EasyExcel.write(outputStream)
                .head(list)
                .registerWriteHandler(new FreezeAndFilter())
                .registerWriteHandler(new SimpleRowHeightStyleStrategy((short) 30, null))
                .registerWriteHandler(new CustomCellWriteHandler())
                .registerWriteHandler(horizontalCellStyleStrategy)
                .sheet("今日新增")
                .doWrite(dataList);

        return new ByteArrayInputStream(outputStream.toByteArray());
    }

    @Override
    public StatisticsPageVO selectStatisticsCount(String companyIds, String type, TokenUser tokenUser) {
        List<String> companyIdList;
        if (!StringUtils.isEmpty(companyIds)) {
            companyIdList = ArrayKit.split(companyIds, ",").stream().distinct().collect(Collectors.toList());
            StatisticsPageVO statisticsPageVO = new StatisticsPageVO();
            if (TYPE_COMPANY.equals(type)) {
                statisticsPageVO.setCompanyGroupCount(
                        groupCompanyService.selectByCompanyIds(companyIdList, tokenUser.getSiteId()).size());
            } else if (TYPE_SITE.equals(type)) {
                // 用工单位树
                List<ChildCompanyListVO> companyListVOList = childCompanyService.select(new ChildCompanyQuery(), tokenUser);
                // 用工单位分组
                List<ChildCompanyListVO> groupCompanyList = getGroupCompany(companyListVOList);
                statisticsPageVO.setCompanyGroupCount(groupCompanyList.size());
            } else if (TYPE_GROUP.equals(type)) {
                statisticsPageVO.setCompanyGroupCount(1);
            } else {
                throw new ParamException("查询类型错误");
            }
            statisticsPageVO.setChildCompanyCount("1");
            statisticsPageVO.setUnitCount(companyIdList.size() + "");
            statisticsPageVO.setStaffCount(empInfoService.selectCountByCompanyIdList(companyIdList, tokenUser) + "");
            statisticsPageVO.setWaitStaffCount(empInfoService.selectWaitEmpCountByCompanyIdList(companyIdList, tokenUser) + "");
            statisticsPageVO.setLeaveStaffCount(empInfoService.selectLeaveEmpCountByCompanyIdList(companyIdList, tokenUser) + "");
            return statisticsPageVO;
        } else {
            return statisticsPageDao.selectStatisticsCount(tokenUser.getSiteId());
        }
    }

    @Override
    public Page<CompanyListVO> selectCompanyAndEmpCount(TokenUser tokenUser, CompanyQuery companyQuery) {
        List<CompanyListVO> companyListVOList = statisticsPageDao.selectComanyAndEmpCount(
                tokenUser.getSiteId(), companyQuery.getName(), companyQuery.getIds());
        if (CollectionUtils.isEmpty(companyListVOList)) {
            return new Page<>(companyQuery.getPageSize(), companyQuery.getPageNo());
        }
        // 校验登录用户权限
        UserCompanyVO userCompanyVO = childCompanyService.selectByUserId(tokenUser.getUserId(), tokenUser.getSiteId());
        // 非总公司权限 查询条件加入用户管理的公司
        if (!userCompanyVO.getIsAllChildCompany()) {
            List<String> companyIdList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(userCompanyVO.getCompanyIds())) {
                companyIdList.addAll(userCompanyVO.getCompanyIds());
            }
            if (!CollectionUtils.isEmpty(userCompanyVO.getGroupIds())) {
                List<GroupCompanyDO> groupCompanyDOList = groupCompanyService
                        .selectByGroupIds(userCompanyVO.getGroupIds(), tokenUser.getSiteId());
                if (!CollectionUtils.isEmpty(groupCompanyDOList)) {
                    companyIdList.addAll(groupCompanyDOList.parallelStream()
                            .map(GroupCompanyDO::getCompanyId).distinct().collect(Collectors.toList()));
                }
            }
            companyListVOList = companyListVOList.parallelStream().filter(companyListVO
                    -> companyIdList.contains(companyListVO.getId())).parallel().collect(Collectors.toList());
        }
        return ListKit.listToPage(companyListVOList, companyQuery.getPageNo(), companyQuery.getPageSize());
    }


    @Override
    public List<CompanyListVO> selectAll(TokenUser tokenUser, CompanyQuery companyQuery) {
        return statisticsPageDao.selectComanyAndEmpCount(
                tokenUser.getSiteId(), companyQuery.getName(), companyQuery.getIds());
    }

    @Override
    public Page<StatisticsEmpInfoVO> selectAllStaff(EmpBySiteQuery empBySiteQuery, TokenUser tokenUser) {
        if (StrKit.isNotEmpty(empBySiteQuery.getTags())) {
            List<String> tagList = ArrayKit.split(empBySiteQuery.getTags(), ",");
            empBySiteQuery.setTagList(tagList);
        }
        if (empBySiteQuery.getOrders() != null) {
            empBySiteQuery.getOrders().forEach(order -> {
                order.setProperty(StrKit.camel2underscore(order.getProperty()));
            });
        }
        PageInfo<StatisticsEmpInfoVO> objectPageInfo = PageHelper.startPage(empBySiteQuery.getPageNo()
                        , empBySiteQuery.getPageSize())
                .doSelectPageInfo(() ->
                        statisticsPageDao.selectAllStaff(empBySiteQuery, tokenUser.getSiteId()));
        Page<StatisticsEmpInfoVO> page = new Page<>(objectPageInfo.getList(), empBySiteQuery.getPageNo(),
                empBySiteQuery.getPageSize(), (int) objectPageInfo.getTotal());
        if (CollectionUtils.isEmpty(page.getEntities())) {
            return new Page<>(empBySiteQuery.getPageSize(), empBySiteQuery.getPageNo());
        }
        //获取员工和部门的对应map
        Map<String, List<EmpReduceInfoVO>> empDepMap = empInfoService.getEmpDepMap(null, tokenUser.getSiteId());
        //获取员工和岗位的对应map
        List<String> empIds = page.getEntities().parallelStream().map(StatisticsEmpInfoVO::getId).collect(Collectors.toList());
        Map<String, List<EmpReduceInfoVO>> empPositionMap = empInfoService.getEmpPositionMap(null, tokenUser.getSiteId());
        //查询所有自定义字段
        List<CompanyAdditionalFieldsListVO> companyAdditionalFieldsListVOList =
                companyAdditionalFieldsService.selectByCompanyId2("site", null, tokenUser.getSiteId());
        Map<String, Map<Long, String>> empAdditionalContent = getEmpAdditionalContent(empIds, tokenUser);
        for (StatisticsEmpInfoVO empInfo : page.getEntities()) {
            String empId = empInfo.getId();
            // 查询此人的紧急联系人列表,取第一个出去
            List<EmpContactsDO> empContactsDOList = empContactsService.listByEmpId(empId, tokenUser.getSiteId());
            log.info("------------------" + System.currentTimeMillis());
            if (!CollectionUtils.isEmpty(empContactsDOList)) {
                empInfo.setContactsName(empContactsDOList.get(0).getName());
                empInfo.setContactsPhone(empContactsDOList.get(0).getPhone());
                empInfo.setContactsRelation(empContactsDOList.get(0).getRelation());
                empInfo.setContactsAddress(empContactsDOList.get(0).getAddress());
            } else {
                // 没有紧急联系人,就赋空值
                empInfo.setContactsName("");
                empInfo.setContactsPhone("");
                empInfo.setContactsRelation("");
                empInfo.setContactsAddress("");
            }
            // 年龄赋值
            if (StringUtils.isNotBlank(empInfo.getIdCard()) && StringUtils.isBlank(empInfo.getBirthday())) {
                int age = DateUtils.getYearDiff(DateKit8.parseDateTime(empInfo.getBirthday()), new Date(System.currentTimeMillis()));
                empInfo.setEmpAge(age);
            }
            // 赋值最高学历和学位
            Map<String, String> highestEducationAndDegree = empEducationService.selectHighestEducationAndDegree(empId);

            // 学历赋值
            empInfo.setHighestEducation(highestEducationAndDegree.get("education"));
            // 学位赋值
            empInfo.setDegreeType(highestEducationAndDegree.get("degree"));
            // 毕业院校
            empInfo.setGraCollege(highestEducationAndDegree.get("graCollege"));
            // 毕业专业
            empInfo.setMajor(highestEducationAndDegree.get("major"));
            // 学习形式
            empInfo.setTeaMethods(highestEducationAndDegree.get("teaMethods"));
            empInfo.setDepName(empInfoService.getDepNameByEmpId(empId, empDepMap));
            empInfo.setPositionName(empInfoService.getPositionNameByEmpId(empId, empPositionMap));
            String needComplete = empInfoService.notComplete(empInfo.getCompanyId(), empId, tokenUser);
            empInfo.setIsImprove(StringUtils.isBlank(needComplete));
            empInfo.setNeedComplete(needComplete);
            // 渠道名称赋值
            String channelName = "";
            if (StrKit.isNotEmpty(empInfo.getChannelId())) {
                ChannelDO channelDO = channelService.selectDOById(empInfo.getChannelId(), tokenUser.getSiteId());
                if (Objects.nonNull(channelDO)) {
                    channelName = channelDO.getName();
                }
            }
            empInfo.setChannelName(channelName);
            // 自定义字段属性 租户自定义字段Id-员工自定义属性值
            Map<String, String> data = new HashMap<>();
            Map<Long, String> additionalIdContentMap = empAdditionalContent.get(empId);
            for (CompanyAdditionalFieldsListVO companyAdditionalFieldsListVO : companyAdditionalFieldsListVOList) {
                String content = additionalIdContentMap.get(companyAdditionalFieldsListVO.getId());
                data.put(SafeKit.getString(companyAdditionalFieldsListVO.getId()), content);
            }
            empInfo.setData(data);
        }
        List<StatisticsEmpInfoVO> entities = page.getEntities();
        List<String> empIdList = entities.stream()
                .map(StatisticsEmpInfoVO::getId).collect(Collectors.toList());

        long l1 = System.currentTimeMillis();
        // 查询花名册电子合同
        List<EmpContractDO> empContractDOS = empContractService.selectByEmpIds(empIdList);
        long l2 = System.currentTimeMillis();
        log.info("员工概览查询查询花名册电子合同,耗时：{}ms", (l2 - l1));

        // 员工-电子合同 Map
        Map<String, List<EmpContractDO>> empIdContractList = empContractDOS.parallelStream()
                .sorted(Comparator.comparing(EmpContractDO::getGmtCreate).reversed())
                .collect(Collectors.groupingBy(EmpContractDO::getEmpId, Collectors.toList()));
        long l3 = System.currentTimeMillis();
        // 查询花名册纸质合同
        List<EmpPaperContractDO> empPaperContracts = empPaperContractService
                .listContractByEmpIdList(empIdList, tokenUser);
        log.info("员工概览查询查询花名册纸质合同,耗时：{}ms", (l3 - l2));

        // 员工-纸质合同 Map
        Map<String, List<EmpPaperContractDO>> empIdPaperContractList = empPaperContracts.parallelStream()
                .sorted(Comparator.comparing(EmpPaperContractDO::getGmtCreate).reversed())
                .collect(Collectors.groupingBy(EmpPaperContractDO::getEmpId, Collectors.toList()));

        long l4 = System.currentTimeMillis();
        for (StatisticsEmpInfoVO entity : entities) {
            String empId = entity.getId();
            List<EmpContractDO> contracts = empIdContractList.get(empId);
            List<EmpPaperContractDO> paperContracts = empIdPaperContractList.get(empId);
            // 合同字段赋值
            setContractInfo(entity, contracts, paperContracts);
        }
        log.info("员工概览查询赋值合同信息,耗时：{}ms", (l4 - l3));

        page.setEntityCount((int) objectPageInfo.getTotal());

        //花名册表头查询
        try {
            CompanyAdditionalFieldsQuery companyAdditionalFieldsQuery = new CompanyAdditionalFieldsQuery();
            companyAdditionalFieldsQuery.setModuleCode("员工概览列表");
            List<CompanyAdditionalFieldsListVO> select = companyAdditionalFieldsService.select(companyAdditionalFieldsQuery, tokenUser.getSiteId());
            if (CollectionUtils.isEmpty(select)) {
                //表头初始化
                for (int i = 0; i < 42; i++) {
                    CompanyAdditionalFieldsAddDTO companyAdditionalFieldsAddDTO = new CompanyAdditionalFieldsAddDTO();
                    companyAdditionalFieldsAddDTO.setFieldType(2);
                    companyAdditionalFieldsAddDTO.setModuleCode("员工概览列表");
                    companyAdditionalFieldsAddDTO.setSort(i);
                    if (i < 8) {
                        companyAdditionalFieldsAddDTO.setIsOpen(true);
                    } else {
                        companyAdditionalFieldsAddDTO.setIsOpen(false);
                    }
                    companyAdditionalFieldsAddDTO.setIsEdit(1);
                    if (i == 0) {
                        companyAdditionalFieldsAddDTO.setIsEdit(0);
                        companyAdditionalFieldsAddDTO.setFieldName("姓名");
                        companyAdditionalFieldsAddDTO.setDescription("name");
                    } else if (i == 1) {
                        companyAdditionalFieldsAddDTO.setFieldName("手机号");
                        companyAdditionalFieldsAddDTO.setDescription("phone");
                    } else if (i == 2) {
                        companyAdditionalFieldsAddDTO.setFieldName("用工单位");
                        companyAdditionalFieldsAddDTO.setDescription("companyName");
                    } else if (i == 3) {
                        companyAdditionalFieldsAddDTO.setFieldName("工作性质");
                        companyAdditionalFieldsAddDTO.setDescription("formalType");
                    } else if (i == 4) {
                        companyAdditionalFieldsAddDTO.setFieldName("员工类型");
                        companyAdditionalFieldsAddDTO.setDescription("employmentType");
                    } else if (i == 5) {
                        companyAdditionalFieldsAddDTO.setFieldName("合同签署状态");
                        companyAdditionalFieldsAddDTO.setDescription("contractsStatus");
                    } else if (i == 6) {
                        companyAdditionalFieldsAddDTO.setFieldName("信息补充（必填项）");
                        companyAdditionalFieldsAddDTO.setDescription("isImprove");
                    } else if (i == 7) {
                        companyAdditionalFieldsAddDTO.setFieldName("实名认证");
                        companyAdditionalFieldsAddDTO.setDescription("verified");
                    } else if (i == 8) {
                        companyAdditionalFieldsAddDTO.setFieldName("现居地址");
                        companyAdditionalFieldsAddDTO.setDescription("currentLocation");
                    } else if (i == 9) {
                        companyAdditionalFieldsAddDTO.setFieldName("学历");
                        companyAdditionalFieldsAddDTO.setDescription("highestEducation");
                    } else if (i == 10) {
                        companyAdditionalFieldsAddDTO.setFieldName("学位");
                        companyAdditionalFieldsAddDTO.setDescription("degreeType");
                    } else if (i == 11) {
                        companyAdditionalFieldsAddDTO.setFieldName("毕业院校");
                        companyAdditionalFieldsAddDTO.setDescription("graCollege");
                    } else if (i == 12) {
                        companyAdditionalFieldsAddDTO.setFieldName("性别");
                        companyAdditionalFieldsAddDTO.setDescription("gender");
                    } else if (i == 13) {
                        companyAdditionalFieldsAddDTO.setFieldName("部门");
                        companyAdditionalFieldsAddDTO.setDescription("positionName");
                    } else if (i == 14) {
                        companyAdditionalFieldsAddDTO.setFieldName("出生日期");
                        companyAdditionalFieldsAddDTO.setDescription("birthday");
                    } else if (i == 15) {
                        companyAdditionalFieldsAddDTO.setFieldName("年龄");
                        companyAdditionalFieldsAddDTO.setDescription("empAge");
                    } else if (i == 16) {
                        companyAdditionalFieldsAddDTO.setFieldName("婚姻状况");
                        companyAdditionalFieldsAddDTO.setDescription("maritalStatus");
                    } else if (i == 17) {
                        companyAdditionalFieldsAddDTO.setFieldName("生育状况");
                        companyAdditionalFieldsAddDTO.setDescription("birthStatus");
                    } else if (i == 18) {
                        companyAdditionalFieldsAddDTO.setFieldName("民族");
                        companyAdditionalFieldsAddDTO.setDescription("nation");
                    } else if (i == 19) {
                        companyAdditionalFieldsAddDTO.setFieldName("政治面貌");
                        companyAdditionalFieldsAddDTO.setDescription("politicalStatus");
                    } else if (i == 20) {
                        companyAdditionalFieldsAddDTO.setFieldName("户口性质");
                        companyAdditionalFieldsAddDTO.setDescription("regType");
                    } else if (i == 21) {
                        companyAdditionalFieldsAddDTO.setFieldName("毕业专业");
                        companyAdditionalFieldsAddDTO.setDescription("major");
                    } else if (i == 22) {
                        companyAdditionalFieldsAddDTO.setFieldName("学习形式");
                        companyAdditionalFieldsAddDTO.setDescription("teaMethods");
                    } else if (i == 23) {
                        companyAdditionalFieldsAddDTO.setFieldName("紧急联系人姓名");
                        companyAdditionalFieldsAddDTO.setDescription("emerContact");
                    } else if (i == 24) {
                        companyAdditionalFieldsAddDTO.setFieldName("紧急联系人电话");
                        companyAdditionalFieldsAddDTO.setDescription("emerPhone");
                    } else if (i == 25) {
                        companyAdditionalFieldsAddDTO.setFieldName("工资卡卡号");
                        companyAdditionalFieldsAddDTO.setDescription("bankCard");
                    } else if (i == 26) {
                        companyAdditionalFieldsAddDTO.setFieldName("银行名称");
                        companyAdditionalFieldsAddDTO.setDescription("bankName");
                    } else if (i == 27) {
                        companyAdditionalFieldsAddDTO.setFieldName("工资卡开户城市");
                        companyAdditionalFieldsAddDTO.setDescription("bankPlace");
                    } else if (i == 28) {
                        companyAdditionalFieldsAddDTO.setFieldName("工资卡开户支行");
                        companyAdditionalFieldsAddDTO.setDescription("bankCardBranch");
                    } else if (i == 29) {
                        companyAdditionalFieldsAddDTO.setFieldName("个人社保账号");
                        companyAdditionalFieldsAddDTO.setDescription("socCard");
                    } else if (i == 30) {
                        companyAdditionalFieldsAddDTO.setFieldName("个人公积金账号");
                        companyAdditionalFieldsAddDTO.setDescription("pfCard");
                    } else if (i == 31) {
                        companyAdditionalFieldsAddDTO.setFieldName("合同类型");
                        companyAdditionalFieldsAddDTO.setDescription("contractType");
                    } else if (i == 32) {
                        companyAdditionalFieldsAddDTO.setFieldName("合同开始时间");
                        companyAdditionalFieldsAddDTO.setDescription("contractStartTime");
                    } else if (i == 33) {
                        companyAdditionalFieldsAddDTO.setFieldName("合同结束时间");
                        companyAdditionalFieldsAddDTO.setDescription("contractEndTime");
                    } else if (i == 34) {
                        companyAdditionalFieldsAddDTO.setFieldName("合同期限");
                        companyAdditionalFieldsAddDTO.setDescription("contactsTerm");
                    } else if (i == 35) {
                        companyAdditionalFieldsAddDTO.setFieldName("备注");
                        companyAdditionalFieldsAddDTO.setDescription("remark");
                    } else if (i == 36) {
                        companyAdditionalFieldsAddDTO.setFieldName("标签");
                        companyAdditionalFieldsAddDTO.setDescription("tag");
                    } else if (i == 37) {
                        companyAdditionalFieldsAddDTO.setFieldName("渠道");
                        companyAdditionalFieldsAddDTO.setDescription("channelName");
                    } else if (i == 38) {
                        companyAdditionalFieldsAddDTO.setFieldName("身份证号");
                        companyAdditionalFieldsAddDTO.setDescription("idCard");
                    } else if (i == 39) {
                        companyAdditionalFieldsAddDTO.setFieldName("户籍地址");
                        companyAdditionalFieldsAddDTO.setDescription("nativeLocation");
                    } else if (i == 40) {
                        companyAdditionalFieldsAddDTO.setFieldName("血型");
                        companyAdditionalFieldsAddDTO.setDescription("bloodGroup");
                    } else if (i == 41) {
                        companyAdditionalFieldsAddDTO.setFieldName("个人邮箱");
                        companyAdditionalFieldsAddDTO.setDescription("email");
                    }
                    companyAdditionalFieldsService.save(companyAdditionalFieldsAddDTO.to(CompanyAdditionalFieldsDO.class), tokenUser.getSiteId(), tokenUser.getUserId());
                }
                //不可见表头

            }
        } catch (Exception e) {
            log.error("花名册表头处理错误，错误信息：" + e);
        }

        return page;

    }

    /**
     * 获取合同信息，花名册电子合同+纸质合同，合并取最新的一条
     */
    private ContractDataVO getContractInfo(List<EmpContractDO> empContractDOS,
                                           List<EmpPaperContractDO> empPaperContractDOS) {
        if (CollectionUtils.isEmpty(empContractDOS) && CollectionUtils.isEmpty(empPaperContractDOS)) {
            return null;
        }
        List<ContractDataVO> contractListSort = getContractListSort(empContractDOS, empPaperContractDOS);
        if (CollectionUtils.isEmpty(contractListSort)) {
            return null;
        }
        return contractListSort.get(0);
    }

    /**
     * 写入员工合同信息，花名册电子合同+纸质合同，合并取最新的一条
     * 产品要求的花名册合同信息展示电子合同+纸质合同，包含：合同开始时间，合同结束时间，合同期限，合同类型
     *
     * @param statisticsEmpInfoVO 员工信息
     * @param empContractDOS      花名册电子合同
     * @param empPaperContractDOS 花名册纸质合同
     */
    private void setContractInfo(StatisticsEmpInfoVO statisticsEmpInfoVO, List<EmpContractDO> empContractDOS,
                                 List<EmpPaperContractDO> empPaperContractDOS) {
        if (CollectionUtils.isEmpty(empContractDOS) && CollectionUtils.isEmpty(empPaperContractDOS)) {
            return;
        }
        List<ContractDataVO> contractListSort = getContractListSort(empContractDOS, empPaperContractDOS);
        if (CollectionUtils.isEmpty(contractListSort)) {
            return;
        }
        ContractDataVO contractDataVO = contractListSort.get(0);
        // 赋值合同类型
        statisticsEmpInfoVO.setContractType(contractDataVO.getFileType());
        // 赋值合同名称
        statisticsEmpInfoVO.setContractName(contractDataVO.getName());
        // 赋值合同开始时间
        statisticsEmpInfoVO.setContractStartTime(contractDataVO.getStartDate());
        // 赋值合同结束时间
        statisticsEmpInfoVO.setContractEndTime(contractDataVO.getEndDate());

        // 统一处理为月份
        int month = contractDataVO.getDateline();
        if (month % 12 == 0) {
            statisticsEmpInfoVO.setContactsTerm(month / 12 + "年");
        } else {
            statisticsEmpInfoVO.setContactsTerm(month + "个月");
        }
    }

    /**
     * 将花名册电子合同，花名册纸质合同处理为统一格式并排序
     * 规则：开始时间最近的，开始时间相同取创建时间最近的
     *
     * @param empContractDOS      花名册电子合同
     * @param empPaperContractDOS 花名册纸质合同
     * @return 合同排序
     */
    private List<ContractDataVO> getContractListSort(List<EmpContractDO> empContractDOS,
                                                     List<EmpPaperContractDO> empPaperContractDOS) {
        // 花名册电子合同转为合同
        List<ContractDataVO> contractDataVOS = empContractToContractList(empContractDOS);
        // 花名册纸质合同转为合同
        List<ContractDataVO> contractDOS1 = empPaperContractToContractList(empPaperContractDOS);
        // 合并
        contractDataVOS.addAll(contractDOS1);
        if (CollectionUtils.isEmpty(contractDataVOS)) {
            return new ArrayList<>();
        }
        List<ContractDataVO> dataVOList = contractDataVOS.stream()
                .filter(contractDataVO -> StrKit.isNotEmpty(contractDataVO.getStartDate()))
                .sorted(Comparator.comparing(ContractDataVO::getStartDate, Comparator.reverseOrder())
                        .thenComparing(ContractDataVO::getGmtCreate, Comparator.reverseOrder()))
                .collect(Collectors.toList());
        // 避免出现因为没有开始时间导致数据被过滤的情况
        if (!CollectionUtils.isEmpty(dataVOList)) {
            return dataVOList;
        }
        return contractDataVOS.parallelStream()
                .sorted(Comparator.comparing(ContractDataVO::getGmtCreate).reversed())
                .collect(Collectors.toList());
    }

    /**
     * 多线程将花名册电子合同转为合同； List<EmpContractDO> =》 List<ContractDataVO>
     *
     * @param empContractDOS 花名册电子合同
     * @return 合同
     */
    private List<ContractDataVO> empContractToContractList(List<EmpContractDO> empContractDOS) {
        if (CollectionUtils.isEmpty(empContractDOS)) {
            return new ArrayList<>();
        }
        return empContractDOS.parallelStream().map(empContractDO -> {
            ContractDataVO contractDataVO = new ContractDataVO();
            contractDataVO.setFileType(empContractDO.getType());
            contractDataVO.setName(empContractDO.getName());
            contractDataVO.setGmtCreate(empContractDO.getGmtCreate());
            contractDataVO.setStartDate(empContractDO.getStartTime());
            contractDataVO.setEndDate(empContractDO.getEndTime());
            contractDataVO.setDateline(getEmpContractTermMonth(empContractDO));
            return contractDataVO;
        }).collect(Collectors.toList());
    }

    /**
     * 多线程将花名册纸质合同转为合同； List<EmpContractDO> =》 List<ContractDataVO>
     *
     * @param empPaperContractDOS 花名册纸质合同
     * @return 合同
     */
    private List<ContractDataVO> empPaperContractToContractList(List<EmpPaperContractDO> empPaperContractDOS) {
        if (CollectionUtils.isEmpty(empPaperContractDOS)) {
            return new ArrayList<>();
        }
        return empPaperContractDOS.parallelStream().map(empPaperContractDO -> {
            ContractDataVO contractDataVO = new ContractDataVO();
            contractDataVO.setFileType(empPaperContractDO.getType());
            contractDataVO.setName(empPaperContractDO.getName());
            contractDataVO.setGmtCreate(empPaperContractDO.getGmtCreate());
            contractDataVO.setStartDate(empPaperContractDO.getStartTime());
            contractDataVO.setEndDate(empPaperContractDO.getEndTime());
            contractDataVO.setDateline(getEmpPaperContractTermMonth(empPaperContractDO));
            return contractDataVO;
        }).collect(Collectors.toList());
    }

    /**
     * 获取花名册纸质合同期限，单位：月
     */
    private int getEmpPaperContractTermMonth(EmpPaperContractDO empPaperContractDO) {
        if (empPaperContractDO == null) {
            return 0;
        }
        // 纸质合同期限：年
        int LIMIT_TYPE_YEAR = 1;
        // 纸质合同期限：月
        int LIMIT_TYPE_MONTH = 2;
        // 合同时间
        int timeLimit = empPaperContractDO.getTimeLimit() == null ? 0 : empPaperContractDO.getTimeLimit();
        // 时间单位 1：年 2： 月
        Integer timeLimitType = empPaperContractDO.getTimeLimitType();
        if (timeLimitType == null) {
            return 0;
        }
        int monthCount = 0;
        if (Objects.equals(timeLimitType, LIMIT_TYPE_YEAR)) {
            monthCount = 12;
        } else if (Objects.equals(timeLimitType, LIMIT_TYPE_MONTH)) {
            monthCount = 1;
        }
        return timeLimit * monthCount;
    }

    /**
     * 获取花名册电子合同期限，单位：月
     */
    private int getEmpContractTermMonth(EmpContractDO empContractDO) {
        if (empContractDO == null) {
            return 0;
        }
        // 年
        int termYear = empContractDO.getTermYear() == null ? 0 : empContractDO.getTermYear();
        // 月
        int termMonth = empContractDO.getTermMonth() == null ? 0 : empContractDO.getTermMonth();
        // 日
        int termDay = empContractDO.getTermDay() == null ? 0 : empContractDO.getTermDay();
        // 统一处理为月份
        return termYear * 12 + termMonth + termDay / 30;
    }

    @Override
    public List<StatisticsEmpInfoVO> selectAllStaffList(EmpBySiteQuery empBySiteQuery, TokenUser tokenUser) {
        List<StatisticsEmpInfoVO> statisticsEmpInfoVOList = statisticsPageDao.selectAllStaff(empBySiteQuery, tokenUser.getSiteId());
        return statisticsEmpInfoVOList;
    }

    @Override
    public List<ChildCompanyExportVO> getAllChildComanyWithAdminForExport(String name, TokenUser tokenUser, List<String> ids) {
        // 校验登录用户权限
        UserCompanyVO userCompanyVO = childCompanyService.selectByUserId(tokenUser.getUserId(), tokenUser.getSiteId());
        List<String> groupIds = userCompanyVO.getGroupIds();
        if (CollectionUtils.isEmpty(groupIds)) {
            ids = Collections.singletonList("");
        } else {
            if (CollectionUtils.isEmpty(ids)) {
                ids = groupIds;
            } else {
                ids = ids.parallelStream().filter(groupIds::contains).collect(Collectors.toList());
            }
        }
        List<ChildCompanyExportVO> exportList = statisticsPageDao.forExport(name, tokenUser.getSiteId(), ids);
        return listAllChildComanyWithAdmin(exportList, tokenUser);
    }

    @Override
    public List<ChildCompanyExportVO> listAllChildComanyWithAdmin(List<ChildCompanyExportVO> exportList, TokenUser tokenUser) {
        String siteId = tokenUser.getSiteId();
        for (ChildCompanyExportVO childCompanyExportVO : exportList) {
            List<HrUserVO> hrUserList = userProviderService.queryUserList(new UserQuery(), childCompanyExportVO.getId(), siteId);
            //拼管理员名
            if (hrUserList.size() > 0) {
                List<String> nameList = new ArrayList<>();
                hrUserList.forEach(admin -> {
                    nameList.add(admin.getName());
                });
                if (nameList.size() > 0) {
                    childCompanyExportVO.setAdmin(StringUtils.join(nameList, ","));
                }
            }
            //拼地区
            List<GroupCityListVO> groupCityListVOS = groupCityService.listByGroup(childCompanyExportVO.getId(), siteId);
            if (!CollectionUtils.isEmpty(groupCityListVOS) && groupCityListVOS.size() == 1
                    && groupCityListVOS.get(0).getIsAll() != null && groupCityListVOS.get(0).getIsAll()) {
                childCompanyExportVO.setCompanyArea("全部");
            } else if (groupCityListVOS.size() > 0) {
                List<String> nameList = new ArrayList<>();
                groupCityListVOS.forEach(area -> {
                    nameList.add(area.getCityName());
                });
                if (nameList.size() > 0) {
                    childCompanyExportVO.setCompanyArea(StringUtils.join(nameList, ","));
                }
            }

            //拼下属单位
            List<GroupCompanyDO> groupCompanyList = groupCompanyService.listByGroupId(childCompanyExportVO.getId(), siteId);
            List<CompanyVO> companyList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(groupCompanyList)) {
                GroupCompanyDO isAllGroupCompany = groupCompanyList.parallelStream()
                        .filter(GroupCompanyDO::getIsAll)
                        .findFirst().orElse(null);
                if (Objects.nonNull(isAllGroupCompany)) {
                    //companyList = companyService.listVoByIds(siteId, (String[]) null);
                    childCompanyExportVO.setSubCompany("全部");
                } else {
                    // 具体用工单位
                    String[] companyIds = groupCompanyList.parallelStream()
                            .map(GroupCompanyDO::getCompanyId)
                            .distinct()
                            .toArray(String[]::new);
                    if (companyIds.length > 0) {
                        companyList = companyService.listVoByIds(siteId, companyIds);
                    }
                    if (null != companyList && companyList.size() > 0) {
                        List<String> nameList = new ArrayList<>();
                        companyList.forEach(company -> {
                            nameList.add(company.getName());
                        });
                        if (nameList.size() > 0) {
                            childCompanyExportVO.setSubCompany(StringUtils.join(nameList, ","));
                        }
                    }
                }

            }
        }
        return exportList;
    }

    private List<ChildCompanyListVO> getVoListByDoList(List<ChildCompanyDO> doList) {
        if (CollectionUtils.isEmpty(doList)) {
            return doList == null ? null : new ArrayList<>();
        }
        return doList.stream()
                .map(childCompanyDO -> childCompanyDO.to(ChildCompanyListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public Page<EmpContractInfoVO> empContractInfoList(EmpInfoQuery empInfoQuery, TokenUser tokenUser) {
        String companyId = empInfoQuery.getCompanyId();
        ParamException.hasText(companyId, "用工单位id不能为空");
        Page<EmpInfoListVO> empInfoListVOPage = empInfoService.pageBaseOnJobEmpList(empInfoQuery, tokenUser);
        if (CollectionUtils.isEmpty(empInfoListVOPage.getEntities())) {
            return empInfoListVOPage.to(EmpContractInfoVO.class);
        }
        List<String> empIdList = empInfoListVOPage.getEntities().stream()
                .map(EmpInfoListVO::getId).collect(Collectors.toList());
        List<EmpContractDO> empContractDOList = empContractService.selectByCompanyIdAndEmpIds(companyId, empIdList);
        // 员工id-花名册电子合同 Map
        Map<String, List<EmpContractDO>> empIdContractListMap = empContractDOList.stream()
                .collect(Collectors.groupingBy(EmpContractDO::getEmpId));

        Page<EmpContractInfoVO> page = empInfoListVOPage.to(EmpContractInfoVO.class);
        for (EmpContractInfoVO entity : page.getEntities()) {
            String empId = entity.getId();
            List<EmpContractDO> empContractDOS = empIdContractListMap.get(empId);
            String timeLimitStr;
            if (!CollectionUtils.isEmpty(empContractDOS)) {
                List<EmpContractDO> contractDOS = empContractDOS.stream()
                        .sorted(Comparator.comparing(EmpContractDO::getGmtCreate).reversed())
                        .collect(Collectors.toList());
                EmpContractDO empContractDO = contractDOS.get(0);
                // 合同类型
                entity.setType(empContractDO.getType());
                // 结束时间
                entity.setEndTime(DateKit8.format2Date(empContractDO.getEndTime()));
                // 合同期限(年)
                int termYear = empContractDO.getTermYear() == null ? 0 : empContractDO.getTermYear();
                // 合同期限(月)
                int termMonth = empContractDO.getTermMonth() == null ? 0 : empContractDO.getTermMonth();
                int monthCount = termYear * 12 + termMonth;
                if (monthCount == 0) {
                    timeLimitStr = "--";
                } else if (monthCount % 12 == 0) {
                    timeLimitStr = monthCount / 12 + "年";
                } else {
                    timeLimitStr = monthCount + "月";
                }
            } else {
                timeLimitStr = "--";
            }
            entity.setTimeLimitStr(timeLimitStr);
        }
        return page;
    }

    @Override
    public List<ChildCompanyListVO> select(ChildCompanyQuery childCompanyQuery, String siteId) {
        List<ChildCompanyListVO> childCompanyList = getVoListByDoList(selectDO(childCompanyQuery, siteId));
        if (!CollectionUtils.isEmpty(childCompanyList)) {
            // 添加子公司关联信息
            return childCompanyService.addRelationToChildCompany(childCompanyList, siteId);
        }
        return childCompanyList;
    }

    private List<ChildCompanyDO> selectDO(ChildCompanyQuery childCompanyQuery, String siteId) {
        Example example = new Example(ChildCompanyDO.class);
        example.and();
        if (childCompanyQuery.getName() != null) {
            example.and().andLike("name", "%" + childCompanyQuery.getName() + "%");
        }
        example.and().andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        return childCompanyDAO.selectByExample(example);
    }

    @Override
    public List<CompanyVO> getSubCompany(ChildCompanyQuery childCompanyQuery, String siteId) {


        List<GroupCompanyDO> groupCompanyList = statisticsPageDao.getCompanyByNameAndPhone(childCompanyQuery.getId(),
                childCompanyQuery.getName(), siteId);
        if (!CollectionUtils.isEmpty(groupCompanyList)) {
            groupCompanyList = groupCompanyList.stream()
                    .sorted(Comparator.comparing(GroupCompanyDO::getGmtCreate).reversed())
                    .collect(Collectors.toList());
        }
        List<CompanyVO> companyList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(groupCompanyList)) {
            GroupCompanyDO isAllGroupCompany = groupCompanyList.parallelStream()
                    .filter(GroupCompanyDO::getIsAll)
                    .findFirst().orElse(null);
            if (Objects.nonNull(isAllGroupCompany)) {
                companyList = companyService.listVoByIds(siteId, (String[]) null);
            } else {
                // 具体用工单位
                String[] companyIds = groupCompanyList.parallelStream()
                        .map(GroupCompanyDO::getCompanyId)
                        .distinct()
                        .toArray(String[]::new);
                if (companyIds.length > 0) {
                    companyList = companyService.listVoByIds(siteId, companyIds);
                }
            }
        }

        return companyList;

    }

    @Override
    public List<RoleMemberVO> getChildCompanyAdmin(ChildCompanyQuery childCompanyQuery, TokenUser tokenUser) {
        RoleMemberQuery roleMemberQuery = new RoleMemberQuery();
        roleMemberQuery.setCompanyId(childCompanyQuery.getId());
        roleMemberQuery.setUserName(childCompanyQuery.getName());
        roleMemberQuery.setPhone(childCompanyQuery.getName());
        List<RoleMemberVO> roleMemberVOS = permissionProviderService.queryRoleMemberListFilterNameAndPhone(roleMemberQuery, tokenUser);
        return roleMemberVOS;
    }

    @Override
    public List<StatisticsEmpInfoContractCountVO> getStatisticsEmpInfoContractCount(StatisticsContractQuery statisticsContractQuery, TokenUser tokenUser) {
        List<String> companyIdList = null;
        if (!StringUtils.isEmpty(statisticsContractQuery.getCompanyIds())) {
            String[] companyIdArray = statisticsContractQuery.getCompanyIds().split(",");
            companyIdList = Arrays.asList(companyIdArray);
        }
        return statisticsPageDao.StatisticsEmpInfoContractCount(statisticsContractQuery.getDateStart(),
                statisticsContractQuery.getDateEnd(), companyIdList, tokenUser.getSiteId());
    }

    @Override
    public EmpEduCountVO empEduCount(String companyIds, TokenUser tokenUser) {
        List<String> companyIdList = null;
        if (!StringUtils.isEmpty(companyIds)) {
            String[] companyIdArray = companyIds.split(",");
            companyIdList = Arrays.asList(companyIdArray);
        }
        return statisticsPageDao.empEduCount(companyIdList, tokenUser.getSiteId());
    }

    /**
     * 有机会一定要把这改了，员工概览的导出仿照花名册导出写一份
     * 这个人用的sql拼接，map作为接收类型，就怕别人看懂
     */
    @Override
    public String selectAllStaffExport(StatisicsPageEmpExportQuery statisicsPageEmpExportQuery, TokenUser tokenUser) {
        ParamException.notEmpty(statisicsPageEmpExportQuery.getExportColumns(), "查询表头不能为空");

        List<EmpInfoExportColumn> exportColumns = statisicsPageEmpExportQuery.getExportColumns();

        List<String> columnList = new ArrayList<>();
        // 表头
        List<List<String>> headList = new ArrayList<>();
        // 租户自定义字段
        List<CompanyAdditionalFieldsListVO> companyAdditionalFieldsListVOList
                = companyAdditionalFieldsService.selectByCompanyId("site", tokenUser.getSiteId());
        Map<Long, String> fieldIdNameMap = companyAdditionalFieldsListVOList.parallelStream()
                .collect(Collectors.toMap(CompanyAdditionalFieldsListVO::getId, CompanyAdditionalFieldsListVO::getFieldName));

        List<DictItemDO> postTypeList = adminProviderService.selectAllDictItem(null, POST_TYPE, tokenUser);
        Map<String, String> postTypeMap = postTypeList.stream().collect(Collectors.toMap(DictItemDO::getDictItemValue, DictItemDO::getDictItemKey, (key1, key2) -> key2));

        //拼装列名list
        for (EmpInfoExportColumn exportColumn : exportColumns) {
            if (!EXPORT_COLUMN_NAME_MAP.containsKey(exportColumn.getDataIndex())) {
                try {
                    // 是否为自定义项(纯数字)
                    long fieldId = Long.parseLong(exportColumn.getDataIndex());
                    String fieldName = fieldIdNameMap.get(fieldId);
                    if (fieldName == null) {
                        // 不在花名册自定义项中
                        log.error("该列不在花名册自定义项中：{}", exportColumn.getDataIndex());
                        continue;
                    }
                    // 放入表头
                    List<String> head = new ArrayList<>();
                    head.add(fieldName);
                    headList.add(head);
                    continue;
                } catch (NumberFormatException e) {
                    // 非表头项与自定义项
                    log.error("不支持导出该列：{}", exportColumn.getDataIndex());
                    continue;
                }
            }
            List<String> head = new ArrayList<>();
            head.add(exportColumn.getTitle());
            headList.add(head);
            if (StrKit.isNotEmpty(EXPORT_COLUMN_NAME_MAP.get(exportColumn.getDataIndex()))) {
                columnList.add(EXPORT_COLUMN_NAME_MAP.get(exportColumn.getDataIndex()));
            }
        }
        columnList.add(EXPORT_COLUMN_NAME_MAP.get("id"));
        columnList.add(EXPORT_COLUMN_NAME_MAP.get("companyId"));
        // 所有员工的基本信息集合
        List<Map<String, String>> maps = new ArrayList<>();
        String sqlString;
        if (columnList.size() > 0) {
            sqlString = String.join(",", columnList);
            // sql在此处拼接，不易维护
            maps = statisticsPageDao.selectAllStaffExportDynamic(
                    statisicsPageEmpExportQuery.getEmpBySiteQuery(), sqlString,
                    statisicsPageEmpExportQuery.getIdList(), tokenUser.getSiteId());
        }
        List<List<String>> list = new ArrayList<>();
        List<String> empIdList = maps.parallelStream()
                .map(s -> s.get("id")).collect(Collectors.toList());
        long l1 = System.currentTimeMillis();
        // 查询花名册电子合同
        List<EmpContractDO> empContractDOS = empContractService.selectByEmpIds(empIdList);
        long l2 = System.currentTimeMillis();
        log.info("员工概览导出查询花名册电子合同，耗时：{}ms", (l2 - l1));

        // 查询花名册纸质合同
        List<EmpPaperContractDO> empPaperContractDOS = empPaperContractService.listContractByEmpIdList(empIdList, tokenUser);
        long l3 = System.currentTimeMillis();
        log.info("员工概览导出查询花名册纸质合同，耗时：{}ms", (l3 - l2));

        // 员工-电子合同 Map
        Map<String, List<EmpContractDO>> empIdContractList = empContractDOS.parallelStream()
                .sorted(Comparator.comparing(EmpContractDO::getGmtCreate).reversed())
                .collect(Collectors.groupingBy(EmpContractDO::getEmpId, Collectors.toList()));
        // 员工-纸质合同 Map
        Map<String, List<EmpPaperContractDO>> empIdPaperContractList = empPaperContractDOS.parallelStream()
                .sorted(Comparator.comparing(EmpPaperContractDO::getGmtCreate).reversed())
                .collect(Collectors.groupingBy(EmpPaperContractDO::getEmpId, Collectors.toList()));
        List<String> empIds = maps.parallelStream().map(map
                -> map.get("id")).filter(Objects::nonNull).collect(Collectors.toList());
        Map<String, Map<Long, String>> empAdditionalContent = getEmpAdditionalContent(empIds, tokenUser);
        for (Map<String, String> map : maps) {
            //maps是员工基本信息，其中的postType不能写死，要根据每个租户动态判断显示什么字段
            String postType = map.get("postType");
            if (StringUtils.isNotBlank(postType)) {
                map.put("postType", postTypeMap.get(postType));
            }

            // 每个人的信息
            List<String> colList = new ArrayList<>();
            String empId = map.get("id");
            Map<Long, String> additionalIdContentMap = empAdditionalContent.get(empId);
            for (EmpInfoExportColumn exportColumn : exportColumns) {
                ParamException.notNull(empId, "员工信息有误");
                if (!EXPORT_COLUMN_NAME_MAP.containsKey(exportColumn.getDataIndex())) {
                    try {
                        // 是否为自定义项(纯数字)
                        long fieldId = Long.parseLong(exportColumn.getDataIndex());
                        String fieldName = fieldIdNameMap.get(fieldId);
                        if (fieldName == null) {
                            // 不在花名册自定义项中
                            log.error("该列不在花名册自定义项中：{}", exportColumn.getDataIndex());
                            continue;
                        }
                        // 放入内容
                        String content = additionalIdContentMap.get(fieldId);
                        colList.add(content);
                        continue;
                    } catch (NumberFormatException e) {
                        // 非表头项与自定义项
                        log.error("不支持导出该列：{}", exportColumn.getDataIndex());
                        continue;
                    }
                }
                List<EmpContractDO> contractDOS = empIdContractList.get(empId);
                List<EmpPaperContractDO> paperContractDOS = empIdPaperContractList.get(empId);
                // 合同字段赋值
                ContractDataVO contractInfo = getContractInfo(contractDOS, paperContractDOS);

                if (null != contractInfo) {
                    // 赋值合同类型
                    if ("contractType".equals(exportColumn.getDataIndex())) {
                        FileType fileType = FileType.find(contractInfo.getFileType());
                        if (fileType != null) {
                            map.put("contractType", fileType.getDesc());
                        }
                    }
                    // 赋值合同开始时间
                    if ("contractStartTime".equals(exportColumn.getDataIndex())) {
                        map.put("contractStartTime", DateKit8.format2Date(contractInfo.getStartDate()));
                    }
                    // 赋值合同结束时间
                    if ("contractEndTime".equals(exportColumn.getDataIndex())) {
                        map.put("contractEndTime", DateKit8.format2Date(contractInfo.getEndDate()));
                    }
                    // 赋值合同期限
                    if ("contactsTerm".equals(exportColumn.getDataIndex())) {
                        if (contractInfo.getDateline() != null) {
                            String contactsTerm;
                            // 统一处理为月份
                            int month = contractInfo.getDateline();
                            if (month % 12 == 0) {
                                contactsTerm = month / 12 + "年";
                            } else {
                                contactsTerm = month + "个月";
                            }
                            map.put("contactsTerm", contactsTerm);
                        }
                    }
                }
                // 处理开户行城市字段
                if ("bankPlace".equals(exportColumn.getDataIndex())) {
                    String bankPlace = "";
                    String bankPlaceIds = map.get(exportColumn.getDataIndex());
                    if (StrKit.isNotEmpty(bankPlaceIds)) {
                        String[] split = bankPlaceIds.split(",");
                        List<String> bankPlaceIdList = Arrays.asList(split);
                        // 一组地区id
                        if (bankPlaceIdList.size() > 1) {
                            StringBuilder bankPlaceBuilder = new StringBuilder();
                            for (String bankPlaceId : bankPlaceIdList) {
                                String bankPlaceItem = adminProviderService.selectAreaById(bankPlaceId);
                                bankPlaceBuilder.append("-");
                                bankPlaceBuilder.append(bankPlaceItem);
                            }
                            bankPlace = bankPlaceBuilder.toString().replaceFirst("-", "");
                        }
                        // 地区id只有一个
                        else if (bankPlaceIdList.size() == 1) {
                            Long aLong = SafeKit.getLong(bankPlaceIdList.get(0));
                            if (aLong != null) {
                                AreaVO areaVO = adminProviderService.selectAreaVOById(aLong);
                                if (areaVO != null) {
                                    bankPlace = areaVO.getParentName() + "-" + areaVO.getName();
                                }
                            } else {
                                bankPlace = bankPlaceIdList.get(0);
                            }
                        }
                    }
                    colList.add(bankPlace);
                } else {
                    colList.add(map.get(exportColumn.getDataIndex()));
                }
            }
            list.add(colList);
        }


        return ExcelKit.exportExcelDynamic("emptyEmpPage", "员工列表", list, headList);
    }

    /**
     * 获取租户自定义字段id-员工自定义字段的值
     *
     * @param empIds    员工
     * @param tokenUser 登录用户
     * @return 员工Id-{租户自定义字段id-员工自定义字段的值}
     */
    private Map<String, Map<Long, String>> getEmpAdditionalContent(List<String> empIds, TokenUser tokenUser) {
        ParamException.notEmpty(empIds, "没有需要查询的员工");
        // 查询租户所有自定义字段
        List<CompanyAdditionalFieldsListVO> companyAdditionalFieldsListVOList =
                companyAdditionalFieldsService.selectByCompanyId2("site", null, tokenUser.getSiteId());
        // 员工自定义字段所填信息
        List<EmpAdditionalFieldsDO> empAdditionalFieldsDOList = empAdditionalFieldsService
                .selectByEmpIds(empIds, tokenUser.getSiteId());
        Map<String, List<EmpAdditionalFieldsDO>> empMap = empAdditionalFieldsDOList
                .parallelStream().collect(Collectors.groupingBy(EmpAdditionalFieldsDO::getEmpId));
        // 员工自定义字段的信息
        List<CompanyAdditionalFieldsDO> companyAdditionalFieldsDOList = companyAdditionalFieldsService
                .selectDOByIds(empAdditionalFieldsDOList.parallelStream().map(EmpAdditionalFieldsDO::getFieldId)
                        .collect(Collectors.toList()), tokenUser.getSiteId());
        // 员工自定义字段按用工单位分组
        Map<String, List<CompanyAdditionalFieldsDO>> companyIdListMap = companyAdditionalFieldsDOList.parallelStream()
                .collect(Collectors.groupingBy(CompanyAdditionalFieldsDO::getCompanyId));
        // 地区
        List<AreaReduceVO> areaList = adminProviderService.listAllArea();
        Map<String, Map<Long, String>> empIdAdditionalMap = new HashMap<>();
        List<EmpInfoDO> empInfoDOList = empInfoService.selectDoByIds(empIds);
        // 员工-用工单位
        Map<String, String> empIdCompanyIdMap = empInfoDOList.parallelStream()
                .collect(Collectors.toMap(BaseDO::getId, EmpInfoDO::getCompanyId));
        for (String empId : empIds) {
            List<EmpAdditionalFieldsDO> empAdditionalFieldsDOS = empMap.get(empId);
            Map<Long, String> additionalIdContentMap = new HashMap<>();
            if (CollectionUtils.isEmpty(empAdditionalFieldsDOS)) {
                for (CompanyAdditionalFieldsListVO companyAdditionalFieldsListVO : companyAdditionalFieldsListVOList) {
                    additionalIdContentMap.put(companyAdditionalFieldsListVO.getId(), "");
                }
                empIdAdditionalMap.put(empId, additionalIdContentMap);
                continue;
            }
            // 用工单位自定义字段Id-员工所填信息
            Map<Long, String> fieldIdContentMap = empAdditionalFieldsDOS.parallelStream()
                    .filter(empAdditionalFieldsDO -> empAdditionalFieldsDO.getContent() != null)
                    .collect(Collectors.toMap(EmpAdditionalFieldsDO::getFieldId, EmpAdditionalFieldsDO::getContent
                            , (v1, v2) -> v1));
            String companyId = empIdCompanyIdMap.get(empId);
            ParamException.notNull(companyId, "员工的用工单位信息有误，请刷新后重试");
            // 该用工单位的自定义字段
            List<CompanyAdditionalFieldsDO> companyAdditionalFieldsList = companyIdListMap.get(companyId);
            if (CollectionUtils.isEmpty(companyAdditionalFieldsList)) {
                for (CompanyAdditionalFieldsListVO companyAdditionalFieldsListVO : companyAdditionalFieldsListVOList) {
                    additionalIdContentMap.put(companyAdditionalFieldsListVO.getId(), "");
                }
                empIdAdditionalMap.put(empId, additionalIdContentMap);
                continue;
            }
            companyAdditionalFieldsList = companyAdditionalFieldsList.parallelStream()
                    .filter(companyAdditionalFieldsDO -> fieldIdContentMap
                            .containsKey(companyAdditionalFieldsDO.getId())).collect(Collectors.toList());
            // 用工单位自定义字段名称-Id
            Map<String, Long> fieldNameIdMap = companyAdditionalFieldsList.parallelStream()
                    .collect(Collectors.toMap(CompanyAdditionalFieldsDO::getFieldName, BaseDO::getId, (v1, v2) -> v1));
            for (CompanyAdditionalFieldsListVO companyAdditionalFieldsListVO : companyAdditionalFieldsListVOList) {
                // 用工单位自定义字段Id
                Long fieldId = fieldNameIdMap.get(companyAdditionalFieldsListVO.getFieldName());
                String content = "";
                if (fieldId != null) {
                    content = fieldIdContentMap.get(fieldId);
                }
                if (content == null) {
                    content = "";
                } else if (companyAdditionalFieldsListVO.getFieldType() == 6) {
                    // 地区信息
                    content = FormatUtils.getNameByCode(content, areaList, ",", "-", "");
                }
                additionalIdContentMap.put(companyAdditionalFieldsListVO.getId(), content);
            }
            empIdAdditionalMap.put(empId, additionalIdContentMap);
        }
        return empIdAdditionalMap;
    }

    @Override
    public StatisticsPageVO selectCompanyAndEmpCountStatistics(String companyIds, String type, TokenUser tokenUser) {
        List<String> companyIdList = null;
        if (!StringUtils.isEmpty(companyIds)) {
            String[] companyIdArray = companyIds.split(",");
            companyIdList = Arrays.asList(companyIdArray);
        }
        StatisticsPageVO statisticsPageVO = selectStatisticsCount(companyIds, type, tokenUser);
        List<EmpInfoDO> empInfoDOList = empInfoService.selectEmpBySiteIdAndCompanyIdList(companyIdList, tokenUser);
        Map<Integer, Long> empGroupByPostType = empInfoDOList.parallelStream()
                .collect(Collectors.groupingBy(EmpInfoDO::getPostType, Collectors.counting()));
        List<DictItemDO> postTypeList = adminProviderService.selectAllDictItem(null, POST_TYPE, tokenUser);
        Map<String, DictItemDO> itemMap = postTypeList.stream()
                .collect(Collectors.toMap(DictItemDO::getDictItemValue, v -> v));
        List<KeyNameVO> keyValueList = new ArrayList<>();
        KeyNameVO companyCountKey = new KeyNameVO();
        companyCountKey.setKey("用工单位数量");
        companyCountKey.setValue(statisticsPageVO.getUnitCount());
        keyValueList.add(companyCountKey);
        for (String postType : itemMap.keySet()) {
            int postTypeCode = Integer.parseInt(postType);
            Long count = empGroupByPostType.get(postTypeCode);
            if (ObjectUtils.isEmpty(count)) {
                count = 0L;
            }
            DictItemDO dictItem = itemMap.get(postType);
            KeyNameVO postTypeDict = new KeyNameVO();
            postTypeDict.setKey(dictItem.getDictItemKey());
            postTypeDict.setValue(count + "");
            keyValueList.add(postTypeDict);
        }
        statisticsPageVO.setSiteContractLeftCount(contractProviderService.getSiteContractLeftCount(tokenUser.getSiteId()));
        statisticsPageVO.setSiteMessageLeftCount(messageProviderService.getSiteMessageLeftCount(tokenUser.getSiteId()));
        SiteDO siteDO = adminProviderService.selectSiteMap().get(tokenUser.getSiteId());
        statisticsPageVO.setSitePic(siteDO.getPic());
        statisticsPageVO.setSiteName(siteDO.getName());
        statisticsPageVO.setKeyNameList(keyValueList);
        return statisticsPageVO;

    }

    @Override
    public StatisticsPageVO selectSocCount(String year, String month, String companyIds, TokenUser tokenUser) {
        List<String> companyIdList = null;
        if (!StringUtils.isEmpty(companyIds)) {
            String[] companyIdArray = companyIds.split(",");
            companyIdList = Arrays.asList(companyIdArray);
        }
        StatisticsPageVO statisticsPageVO = new StatisticsPageVO();
        Map<String, Long> empSocStatusMap = empSocInfoService
                .selectHomeSocCount(tokenUser, year, month, companyIdList, tokenUser.getSiteId());
        statisticsPageVO.setSocCount(empSocStatusMap.get(NORMAL_SOC_STR));
        statisticsPageVO.setIncreaseCount(empSocStatusMap.get(INCREASE_STR));
        statisticsPageVO.setDecreaseCount(empSocStatusMap.get(DECREASE_STR));
        return statisticsPageVO;
    }

    @Override
    public Page<ServiceLogListVO> selectServiceLog(ServiceLogFillQuery serviceLogQuery, TokenUser tokenUser) {
        // 公司Id字符串转List
        List<String> companyIdList = null;
        if (!StringUtils.isEmpty(serviceLogQuery.getCompanyStr())) {
            String[] companyIdArray = serviceLogQuery.getCompanyStr().split(",");
            companyIdList = Arrays.asList(companyIdArray);
        }
        ServiceLogQuery logQuery = new ServiceLogQuery();
        // 转换为log模块的query参数
        BeanUtils.copyProperties(serviceLogQuery, logQuery);
        logQuery.setContentIdList(companyIdList);
        Page<ServiceLogListVO> serviceLogListVO = serviceLogProviderService.selectServiceLog(logQuery, tokenUser);
        List<ServiceLogListVO> entities = serviceLogListVO.getEntities();
        if (CollectionUtils.isEmpty(entities)) {
            return new Page<>(serviceLogQuery.getPageSize(), serviceLogQuery.getPageNo());
        }
        for (ServiceLogListVO entity : entities) {
            if (!StringUtils.isEmpty(entity.getContentId())) {
                CompanyDO companyDO = companyService.selectDOByIdNotValid(entity.getContentId(), tokenUser.getSiteId());
                entity.setContentId(companyDO.getName());
            }
        }
        return serviceLogListVO;
    }

    @Override
    public StatisticsPageVO selectHomeEmpCount(TokenUser tokenUser, String year, String month, String companyIds) {
        List<String> companyIdList = null;
        if (!StringUtils.isEmpty(companyIds)) {
            String[] companyIdArray = companyIds.split(",");
            companyIdList = Arrays.asList(companyIdArray);
        }
        return empInfoService.selectHomeEmpCountByMonth(tokenUser, year, month, companyIdList);
    }

    @Override
    public int updateSitePic(String picUrl, TokenUser tokenUser) {
        return adminProviderService.updateSitePic(picUrl, tokenUser);
    }

    @Override
    public Page<ChildCompanyVO> pageChildCompany(ChildCompanyQuery childCompanyQuery, TokenUser tokenUser) {
        String siteId = tokenUser.getSiteId();
        // 用工单位树
        List<ChildCompanyListVO> companyListVOList = childCompanyService.select(childCompanyQuery, tokenUser);
        // 用工单位分组
        List<ChildCompanyListVO> groupCompanyList = getGroupCompany(companyListVOList);
        // 过滤用工单位分组
        List<String> ids = childCompanyQuery.getIds();
        if (!CollectionUtils.isEmpty(ids)) {
            // 如果是批量，过滤分组id
            groupCompanyList = groupCompanyList.stream()
                    .filter(s -> ids.contains(s.getId())).collect(Collectors.toList());
        }
        Page<ChildCompanyListVO> childCompanyListVOPage = PageKit.startPage(groupCompanyList, childCompanyQuery.getPageNo(),
                childCompanyQuery.getPageSize());
        Page<ChildCompanyVO> page = childCompanyListVOPage.to(ChildCompanyVO.class);
        List<ChildCompanyVO> entities = page.getEntities();
        if (!CollectionUtils.isEmpty(entities)) {
            for (ChildCompanyVO entity : entities) {
                // 设置用工单位分组分管单位内容
                entity.setCompanyStr(getCompanyContent(entity.getId(), siteId));
            }
        }
        return page;
    }

    @Override
    public List<ChildCompanyVO> listChildCompany(ChildCompanyQuery childCompanyQuery, TokenUser tokenUser) {
        String siteId = tokenUser.getSiteId();
        // 用工单位树
        List<ChildCompanyListVO> companyListVOList = childCompanyService.select(childCompanyQuery, tokenUser);
        // 用工单位分组
        List<ChildCompanyListVO> groupCompanyList = getGroupCompany(companyListVOList);
        // 过滤用工单位分组
        List<String> ids = childCompanyQuery.getIds();
        if (!CollectionUtils.isEmpty(ids)) {
            // 如果是批量，过滤分组id
            groupCompanyList = groupCompanyList.stream()
                    .filter(s -> ids.contains(s.getId())).collect(Collectors.toList());
        }
        List<ChildCompanyVO> childCompanyVOList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(groupCompanyList)) {
            childCompanyVOList = groupCompanyList.stream()
                    .map(s -> s.to(ChildCompanyVO.class)).collect(Collectors.toList());
            for (ChildCompanyVO item : childCompanyVOList) {
                // 设置用工单位分组分管单位内容
                item.setCompanyStr(getCompanyContent(item.getId(), siteId));
            }
        }
        return childCompanyVOList;
    }

    @Override
    public List<GroupCompanyExportVO> exportChildCompany(ChildCompanyQuery childCompanyQuery, TokenUser tokenUser) {
        List<ChildCompanyVO> childCompanyVOList = listChildCompany(childCompanyQuery, tokenUser);
        if (CollectionUtils.isEmpty(childCompanyVOList)) {
            return new ArrayList<>();
        }
        return childCompanyVOList.stream().map(item -> item.to(GroupCompanyExportVO.class)).collect(Collectors.toList());
    }

    /**
     * 获取用工单位分组分管单位内容
     *
     * @param childCompanyId 用工单位分组id
     * @param siteId         租户id
     * @return 文本显示内容
     */
    private String getCompanyContent(String childCompanyId, String siteId) {
        String content = null;
        List<String> companyIdList = groupCompanyService.selectCompanyIdListByGroupIds(Collections.singletonList(childCompanyId), siteId);
        if (!CollectionUtils.isEmpty(companyIdList)) {
            List<CompanyDO> companyDOList = companyService.selectBaseCompanyByIdList(companyIdList, siteId)
                    .stream()
                    .sorted(Comparator.comparing(CompanyDO::getGmtCreate).reversed())
                    .collect(Collectors.toList());
            int size = companyDOList.size();
            if (size >= 2) {
                content = companyDOList.get(0).getName() + "、" + companyDOList.get(1).getName() + "等" + size + "家用工单位";
            } else if (size >= 1) {
                content = companyDOList.get(0).getName();
            } else {

            }
        }
        return content;
    }

    /**
     * 获取用工单位分组
     *
     * @param companyListVOList 查询出的用工单位树
     * @return 用工单位分组
     */
    private List<ChildCompanyListVO> getGroupCompany(List<ChildCompanyListVO> companyListVOList) {
        List<ChildCompanyListVO> groupCompanyList = new ArrayList<>();
        getGroupCompany(companyListVOList, groupCompanyList);
        return groupCompanyList;
    }

    /**
     * 递归获取用工单位树中的分组
     *
     * @param companyListVOList 查询出的用工单位树
     * @param groupCompanyList  用工单位分组
     */
    private void getGroupCompany(List<ChildCompanyListVO> companyListVOList, List<ChildCompanyListVO> groupCompanyList) {
        if (!CollectionUtils.isEmpty(companyListVOList)) {
            for (ChildCompanyListVO childCompanyListVO : companyListVOList) {
                if ("group".equals(childCompanyListVO.getType())) {
                    groupCompanyList.add(childCompanyListVO);
                } else if ("site".equals(childCompanyListVO.getType())) {
                    getGroupCompany(childCompanyListVO.getCompanyList(), groupCompanyList);
                }
            }
        }
    }

}
